
 SWIs
 ====
 From version 0.17, the HBP10GM supports multiple ports; this
 means that you can generate samples for multiple MIDI data
 streams simultaneously. Most of the API (and all of the
 *-commands) manipulates the default port, which is also the
 only port that can receive data from the scheduler or from
 the MIDISupport module.
 The remaining ports can be created and deleted using
 SWI HBP10GM_Ports. The same SWI is also used for sending
 MIDI events to the ports and for reading samples from the
 ports.

 Notice that the module may enable interrupt whilst processing
 the incoming data, thus routines that call SWI MIDI_TxBytes,
 MIDI_TxCommand or MIDI_Scheduler must be able to handle
 reentrancy.

 ----------------------------------------------------------
 SWI HBP10GM_TxBytes                                 &54f00
 This inserts bytes into the MIDI buffer for immediate processing.

     On entry
          R0 ->  buffer
          R1 =   no. of bytes
     On exit
          R0 =   unused bytes left in the MIDI buffer


 ----------------------------------------------------------
 SWI HBP10GM_ReadSamples                             &54f01
 Reads samples from the synthesizer.

     On entry
          R0 ->  buffer (stereo, 32 bits/samples)
          R1 =   no. of samples to read
                 (should be in the range 50..50000)
          R2 =   flags
                 bit 0  update ticker as specified by bit 1
                 bit 1  clear  increment ticker by
                               tickspersecond*samples/frequency
                 bit 1  set    increment ticker by value in R3
                 bit 2  set    reduce to mono
                 bit 3  set    reset buffer before filling it
                 bit 4  set    reduce to 16 bit
                 bit 5  set    interpolate samples
                 all other bits are reserved and should be set to 0
          R3 =   ticker increment value


 ----------------------------------------------------------
 SWI HBP10GM_TxCommand                               &54f02
 This inserts bytes into the MIDI buffer for immediate processing.
 This is meant for use with for example SWI Sound_QSchedule.

     On entry
          R0 =  &d2d1d0nn       nn   =  no. of bytes
          R1 =  &d6d5d4d3     d0..d6 = up to 7 bytes of data

 Notice that the format is different from that used by 
 SWI MIDI_TxCommand.

 ----------------------------------------------------------
 SWI HBP10GM_Ticker                                  &54f03
 This controls the scheduler.

     On entry
          R0 =  reason code in bits 0..7
                0   reset ticker to 0
                1   read ticker value
                2   set ticker to value in R1
                3   increment ticker by value in R1
                4   set ticks/second
                5   read ticks/second
                6   increment ticker by R1/R2 seconds
                7   flush event buffer
          R1 =  ticker value/increment (if R0=2,3,6)
    or    R1 =  ticks/second (if R0=4)
    or    R1 =  fractions, R2 = fractions/second (if R0=6)
          R2 =  resolution of value in R1 (if R0=6)
     On exit
          R0 =  ticker value (if R0=1 on entry)
    or    R0 =  ticks/second (if R0=5 on entry)

 Ticks/second defaults to 4000.


 ----------------------------------------------------------
 SWI HBP10GM_Schedule                                &54f04
 Schedules a event for later insertion into the MIDI buffer.

     On entry
          R0 =  &d2d1d0nn        nn  =  no. of bytes
          R1 =  &d6d5d4d3     d0..d6 = up to 7 bytes of data
          R2 =  ticker-value (when to insert the event)
                or -2 to schedule as next event
                   -3 to insert at end of event-queue
    or    R0 =  -1 to read info about the buffer
     On exit
          R0 =  -1 (event buffer is full)
    or    R0 =  amount of free space in the event-buffer
          R1 =  ticker-value of first event in the buffer
          R2 =  ticker-value of last event in the buffer
          R3 =  total size of event buffer
          R4 =  current ticker-value
          R5 =  ticks/second
 R1-R5 are only valid if R0=-1 on entry.

 Notice that R0 returns 1 less than it should - to discourage
 users from filling the buffer to the brim.


 ----------------------------------------------------------
 SWI HBP10GM_Playback                                &54f05

     On entry
          R0 =  reason code in bits 0..7
                0   stop playback and kill driver
                1   play through 16 bit Acorn soundcard
                2   read address of internal sample-generating
                    routine
     On exit
          R0 -> internal sample-generating routine
                (if R0=2 on entry)


 The internal sample-generating routine should be called with:

          R0 -> buffer (word-aligned, 32 bits/sample, stereo)
          R1 =  no. of samples to read
          R2 =  flags
                bit 2 clear   output stereo
                bit 2 set     reduce to mono
                bit 3 clear   mix with current buffer-contents
                bit 3 set     clear buffer first
                bit 4 clear   output 32 bit samples
                bit 4 set     reduce to 16 bit samples
                bit 5 clear   don't interpolate samples
                bit 5 set     interpolate samples
                all other bits must be 0
          R13,R14 as usual

 ----------------------------------------------------------
 SWI HBP10GM_ControlSamples                          &54f06
 Read/write/manipulate the sample-data-bank directly.

     On entry
          R0 =  reason code in bits 0..7
                0   get samplehandle
                1   create sample
                2   remove sample
                3   map sample to patch
                4   get sample info
                5   set samplename
                6   enumerate samples
                7   set default sample
                8   get patch info
                9   find sample
                10  find sample address
                11  generate FM waveform

 if R0=0  get sample handle
          R0 also holds the bank/program/note no.:
                bank no. in bits 8..11
                bit 12 set -> drum bank
                program no. in bits 13..19
                note in bits 20..26 (60 for middle-C)
                all other bits are reserved and must be 0
          on exit
          R0 =  samplehandle or -1

 if R0=1  create sample
          R0 also hold flags:
                bit 8..15     format
                              0   16 bit
                              1   8 bit
                bit 16 clear  create internal sample
                bit 16 set    create external sample
                all other bits are reserved and must be 0
          R1 =  length (in sample)
          R2 -> name (max 15 chars, 0-terminated)
          R3 -> sampledata (if external sample)
          R4 =  looppoint
          on exit
          R0 =  samplehandle

          if you're creating an external sample, the sampledata
          is assumed to be stored somewhere in shared memory (RMA
          or dynamic area) - the synth will just store the address
          of the sample; if you're creating an internal sample,
          the synth will allocate memory for the sample - you can
          then use SWI HBP10GM_ControlSamples,10 to read the
          address of the allocated memory

 if R0=2  remove sample
          R1 =  samplehandle

 if R0=3  map sample to patch
          R0 also holds the bank/program/note no.:
                bank no. in bits 8..11
                bit 12 set -> drum bank
                program no. in bits 13..19 (if bit 12 clear)
                note in bits 20..26 (used to select octave
                or drum no.)
                if bit 27 set, the sample will be used
                by all octaves (if bit 12 clear)
                if bit 28 set, R1 points to a samplename
                all other bits are reserved and must be 0
          R1 =  samplehandle or
                pointer to samplename or
                -1 to remove
          R2 =  frequency (middle-C)

 if R0=4  get sample info
          R1 =  samplehandle
          R2 -> buffer to fill (24 bytes)
                +0  length (&7FFFFFFF for infinite)
                +4  looppoint
                +8  name

 if R0=5  set sample name
          R1 =  samplehandle
          R2 -> new name (max 15 chars, 0 terminated)

 if R0=6  enumerate samples
          R1 =  samplehandle (or 0 for first call)
          on exit
          R1 =  next samplehandle (or -1 if there are no more)

 if R0=7  set default sample
          R1 =  samplehandle or -1

 if R0=8  get patch info
          R0 also holds the bank/program/note no.:
                bank no. in bits 8..11
                bit 12 set -> drum bank
                program no. in bits 13..19 (if bit 12 clear)
                note in bits 20..26 (used to select octave
                or drum no.)
          R1 -> buffer for patch name (16 bytes)
          on exit
          R0 =  sample handle or -1
          R2 =  frequency

 if R0=9  find sample
          R1 -> samplename
          on exit
          R0 =  samplehandle

 if R0=10 find sample address
          R1 =  samplehandle
          on exit
          R0 -> sample data buffer


 Samplehandles are numbers from 0..65534

 ----------------------------------------------------------
 SWI HBP10GM_Control                                 &54f07
 Controls/configures the synthesizer

     On entry
          R0 =  reason code in bits 0..7
                0   set/read frequency (7000..50000 Hz)
                1   set/read polyphony (16..64 notes)
                2   set/read master volume (0..4096, 4096=100%)
                3   set/read master tuning (-24 .. 24 semitones)
                4   set/read interpolation (0 disabled, 1 enabled)
                5   set/read basechannel (0..15)
                bit 31 set to just read the old value
                all other bits are reserved and must be 0
          R1 =  new value (if R0,bit31 is clear)
     On exit
          R0 =  old value


 ----------------------------------------------------------
 SWI HBP10GM_Monitor                                 &54f08
 Allows you to read what MIDI-data the HBP10GM receives.

     On entry
          R0 =  reason code in bits 0..7
                0   stop monitoring
                1   start monitoring
                2   read monitor-buffer start address
                3   read current write-position in monitor-buffer
                all other bits are reserved and must be 0
          R1 -> monitor-buffer in shared memory (if R0=1)
                the buffer should be at least 4kbytes
          R2 =  buffer size (if R0=1)
     On exit
          R0 -> current monitor-buffer or 0 (if R0=2)
     or   R0 =  offset of next byte that will be written
                when new data arrives (if R0=3)


 ----------------------------------------------------------
 SWI HBP10GM_ControlChannel                          &54f09
 Controls/configures the channels

     On entry
          R0 =  reason code in bits 0..7
                0   set/read drum-channel-configuration (0 or 1) *
                1   set/read pan-position (0..127)               *
                2   set/read volume (0..127)                     *
                3   set/read selected bank (0..15)               *
                4   set/read program (0..127)                    *

                5   read drum-channel-configuration
                6   read pan position for all channels
                7   read volume for all channels
                8   read selected patchbank for all channels
                9   read program for all channels

                *  channel no. in bits 8..11
                set bit 31 to just read the old value
                all other bits are reserved and must be 0

          R1 =  new value (if R0=0,1,2,3,4 and R0:31 is clear)
          R1 -> 16 bytes buffer to fill (if R0=6,7,8,9)

     On exit
          R0 =  old value (if R0=0,1,2,3,4 on entry)
      or  R0 =  16 bit bitfield (if R0=5 on entry)
      otherwise R0 corrupted


 ----------------------------------------------------------
 SWI HBP10GM_ControlPatches  *** NOT YET SUPPORTED ***
 Controls/configures the patches

     On entry
          R0 =  reason code in bits 0..7
                0  set/read envelope attacktime
                1  set/read envelope holdtime
                2  set/read envelope decaytime
                3  set/read envelope decayamount
                4  set/read envelope sustainfade
                5  set/read max duration
                6  set/read loop-point
                7  set/read middle-C frequency

                bank no. in bits 8..11
                bit 12 set -> drum bank
                program no. in bits 13..19
                all other bits are reserved and must be 0


 ----------------------------------------------------------
 SWI HBP10GM_ExternalVoice                           &54f0b
 This SWI manages the interface to voice generators and other
 extensions.

     On entry
          R0 =  reason code in bits 0..7
                0   install voice generator
                1   remove voice generator

 if R0=0  install voice generator
          bank no. in bits 8..11
          program no. in bits 13..19
          all other bits are reserved and must be 0
          R1 -> control block (in RMA)
          R2 -> voice generator name (max 15 chars)

 if R0=1  remove voice generator
          R1 -> control block


 A voice generator need not output any sound - it may also be
 used to control/synchronise other devices, programs or hardware.

 It would be preferable if voice generators for special purposes
 (like controlling other programs or hardware) all use bank #14
 when possible.


 ----------------------------------------------------------
 SWI HBP10GM_Info                                    &54f0c

     On entry
          R0 =  reason code in bits 0..7
                0   read no. of currently playing notes
                1   read estimated output volume

     On exit
          R0 =  no. of currently playing notes (if R0=0 on entry)
          R0 =  estimated output volume        (if R0=1 on entry)
                bits  0..7   combined l+r
                bits  8..15  left
                bits 16..23  right
                the volume is sort of like in dB's 


 ----------------------------------------------------------
 SWI HBP10GM_Ports                                   &54f0d
 Creates/deletes/controls MIDI ports

     On entry
          R0 =  reason code in bits 0..7
                port no. in bits 8..15 (if reason code <> 0)
                all other bits are reserved and must be 0
                0   create new port
                1   delete port
                2   tx bytes
                3   tx command
                4   tx small command
                5   read samples
                6   read info

 if R0=0  create new port
          R1 =  frequency
          R2 =  features word or 0 for default
                bits  0..3   basechannel
                bits  4..8   tuning (signed 4 bit value)
                bits  9..14  maximum polyphony - 1
          on exit
          R0 =  port number (1..255)

 if R0=1  delete port

 if R0=2  tx bytes
          R1 -> buffer
          R2 =  no. of bytes
          on exit
          R0 =  no. of free bytes left in buffer

 if R0=3  tx command
          R1 =  d2d1d0nn       nn      = no. of data bytes
          R2 =  d6d5d4d3       d0..d6  = up to 7 data bytes
          on exit
          R0 =  no. of free bytes left in buffer

 if R0=4  tx small command
          this is intended for use with SWI Sound_QSchedule
          R1 =  d2d1d0nn       nn      = no. of data bytes
          on exit
          R0 =  no. of free bytes left in buffer

 if R0=5  read samples
          R1 -> buffer (stereo, 32 bits/sample)
          R2 =  number of samples to read
          R3 =  flags
                bit 2 set     stereo
                bit 3 set     clear buffer
                bit 4 set     reduce to 16 bits
                              (instead of 32 bits)
                bit 5 set     interpolate samples

 if R0=6  read info
          not supported

 Notice that the MIDI port' perception of time is alone
 determined by the number of samples that has been read (using
 SWI HBP10GM_Ports,5) and the frequency specified when the
 port was created.

 ----------------------------------------------------------
 SWI HBP10GM_Events                                  &54f0e
 The HBP10GM module generates a number of events which may be
 intercepted or claimed; these are mainly of interest to
 modules which provides voice generators.

 On entry
          R0 =  reason code
                0  claim event
                1  release event
          R1 =  event
          R2 =  address of event handler
          R3 =  value to pass in R12 when calling event handler

 The event handler will be called with
          R0 =  event
          R1 .. R3  arguments
         R12 =  value passed in R3 when claiming event
 On exit  R0 =  0 (to claim the event (don't pass it on))
                1 (to pass on the event)


 Events:
          0         module is dying
          1         missing patch
                    R1 =  bank no.
                    R2 =  program no. / drum no.
                    R3    bit 0 set if channel is drum channel
                    this event is generated whenever the synth
                    tries to play a note using the default
                    sample (ie. the selected program in the
                    selected bank isn't mapped to a sample)
          2         realtime input enabled
                    R1 =  driver type
                          1   MIDI support
                          2   100 Hz
                          3   MIDI 5.00
          3         realtime input disabled
          4         realtime output enabled
          5         realtime output disabled
          6         unknown *HBP10GM_Config <name> <value>
                    R1 -> name
                    R2 =  value
          7         *HBP10GM_Config called without arguments
          8         port created
                    R1 -> port structure
          9         port deleted
                    R1 -> port structure


 ----------------------------------------------------------
 Structures


 Voice generator control block
     +0   flags
          bit 0 set -> monophonic (else polyphonic)
     +4   pointer to event-handler-code
          called with:
             R0  =  reason code in bits 0..7
                    0         note on
                    1         note off
                    2         note has stopped
                    3         fill
                    4         free'ing            (closing down)
             R1  -> control block
             R2  -> controllers for the channel     (if R0=0)
             R2  =  position (0 for first call)     (if R0=3)
             R3  -> buffer to fill (stereo, 32 bps) (if R0=3)
             R4  =  no. of samples to write         (if R0=3)
             R5  =  resample rate                   (if R0=3)
             R6  =  left volume                     (if R0=3)
             R7  =  right volume                    (if R0=3)
             R8  -> private word in note-structure  (if R0=0,1,2,3)
             R12 =  value in +8
          all registers, except R2, R5 and R9 must be preserved -
          if R0=3 (fill), R2 must be updated to the value to use
          the next time the event-handler-code is called with R0=3
     +8   value to pass in R12 when calling the event-handler-code
     +12  frequency (samples/sec to play to get middle-C)


 ----------------------------------------------------------
 Sample code


 The following BASIC program copies all data received by
 the MIDI synthesizer to a file

          REM > monitor
          SYS"OS_Module",6,,,8000 TO ,,B%
          SYS"HBP10GM_Monitor",1,B%,8000
          H%=OPENOUT("$.mididump")
          N%=0
          R%=0
          REPEAT
            SYS"HBP10GM_Monitor",3 TO W%
            IF W%>R% THEN
              SYS"OS_GPBP",2,H%,B%+R%,W%-R%
              R%=W%
            ENDIF
            IF W%<R% THEN
              SYS"OS_GBPB",2,H%,B%+R%,8000-R%
              SYS"OS_GBPB",2,H%,B%,W%
              R%=W%
            ENDIF
          UNTIL INKEY(0)=32
          SYS"HBP10GM_Monitor",0
          CLOSE#H%
          SYS"OS_Module",7,,B%
